package blockchain

import (
	"bytes"
	"crypto/sha256"
	"encoding/gob"
	"log"
	"time"
)
import "blockchain/utils"

// Block keeps block headers
type Block struct {
	Version uint64

	PrevBlockHash []byte
	MerkleRoot    []byte

	Timestamp uint64
	Bits      uint64 // 难度目标
	Nonce     uint64
	Hash      []byte // 为了方便我们将当前区块的hash放在区块中，实际上不是
	Data      []byte // 区块体
}

// NewBlock creates and returns Block
func NewBlock(data string, prevBlockHash []byte) *Block {
	block := &Block{
		Version:       0,
		PrevBlockHash: prevBlockHash,
		MerkleRoot:    nil,
		Timestamp:     uint64(time.Now().Unix()),
		Bits:          0,
		Nonce:         0,
		Hash:          []byte{},
		Data:          []byte(data)}
	//计算哈希值
	//block.setHash()
	pow := NewProofOfWork(block)
	hash, nonce := pow.Run()
	block.Hash = hash
	block.Nonce = nonce
	return block
}

func (b *Block) setHash() {
	tmp := [][]byte{
		utils.IntToHex(int64(b.Version)),
		b.PrevBlockHash,
		b.MerkleRoot,
		utils.IntToHex(int64(b.Timestamp)),
		utils.IntToHex(int64(b.Bits)),
		utils.IntToHex(int64(b.Nonce)),
		b.Data,
	}
	data := bytes.Join(tmp, []byte{})
	hash := sha256.Sum256(data)
	b.Hash = hash[:] // 把数组转换为切片
}

// Serialize serializes the block
func (b *Block) Serialize() []byte {
	var result bytes.Buffer
	encoder := gob.NewEncoder(&result)

	err := encoder.Encode(b)
	if err != nil {
		log.Panic(err)
	}

	return result.Bytes()
}

// DeserializeBlock deserializes a block
// 这个函数不是成员函数
func DeserializeBlock(d []byte) *Block {
	var block Block

	decoder := gob.NewDecoder(bytes.NewReader(d))
	err := decoder.Decode(&block)
	if err != nil {
		log.Panic(err)
	}

	return &block
}
